home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / comm / bbs / cit_src_7H21.lha / netcache.c < prev    next >
C/C++ Source or Header  |  1997-07-27  |  18KB  |  714 lines

  1. /*
  2. *       netcache.c
  3. *
  4. * Networking functions for handling network cache (fast transfers).
  5. */
  6. /*
  7. *       history
  8. *
  9. * 91Sep20 HAW Created.
  10. */
  11. #include "ctdl.h"
  12. #include <dos.h>
  13. #define MAP_FILE  "map.$$$"
  14. #define FAST_TEMPLATE "fast$$$.%s"
  15. #define FAST_RECEIVE  "fast_tr.%s"
  16. #define NETMSGS   "netmsgs.%s"
  17. /*
  18. *       contents
  19. *
  20. */
  21. char RecMassTransfer;
  22. char MassTransferSent;
  23. char Zmodem = 0;
  24. static int MTCompVal;
  25.  
  26.  
  27. extern char logNetResults;
  28. extern char netDebug;
  29.  
  30.  
  31. extern CONFIG    cfg;   /* Lots an lots of variables    */
  32. extern char      *SR_Sent;
  33. extern MessageBuffer   msgBuf;
  34. extern char      inReceive;
  35. extern NetBuffer netTemp;
  36. extern char      inNet;
  37. extern NetBuffer netBuf;
  38. extern FILE  *netLog;
  39. extern rTable    *roomTab;
  40. extern FILE  *upfd;
  41. extern int   callSlot;
  42. extern NetTable  *netTab;
  43. extern int       thisNet;
  44. extern char  *READ_ANY, *APPEND_ANY;
  45. /*
  46. * FileMap
  47. *
  48. * This structure is used to map between a filename and the room it's
  49. * carrying.
  50. */
  51. typedef struct
  52.   {
  53.   char *FileName;
  54.   char *RoomName;
  55.  
  56.   }
  57. FileMap;
  58. /*
  59. * Mappings
  60. *
  61. * This is a list of mappings for our current work.
  62. */
  63. static void FreeMapping();
  64. SListBase Mappings =
  65.   {
  66.   NULL, NULL, NULL, FreeMapping, NULL
  67.  
  68.   };
  69. /*
  70. * SendFastTransfer()
  71. *
  72. * We want to use Facility 21, the mass transfer of messages.
  73. */
  74. char SendFastTransfer()
  75.   {
  76.   long   size;
  77.   extern long netBytes;
  78.   extern AN_UNSIGNED RecBuf[SECTSIZE + 5];
  79.   struct cmd_data cmds;
  80.   char BaseArcName[15], Outgoing;
  81.   int protocol;
  82.   char ArcFileName[100];
  83.   char CacheDir[70];
  84.   int RoomOutgoing(SharedRoom *room, int system, int index, int roomslot,  char *d);
  85.   int UnCacheRoom(SharedRoom *room, int system, int index, int roomslot,  void *d);
  86.  
  87.   if ( logNetResults && netDebug )splitF(netLog, "SendFastTransfer:%sabled\n", netBuf.nbflags.MassTransfer ? " En" : "Dis");
  88.   if (!netBuf.nbflags.MassTransfer)    return FALSE;
  89.   if (!netBuf.nbflags.local &&
  90.   !(netBuf.nbflags.spine || inReceive))
  91.     {
  92.     if( logNetResults )
  93.       {
  94.       if( netDebug )
  95.         {
  96.         if( !netBuf.nbflags.local )splitF(netLog, "SendFastTransfer:FALSE, Not Local\n");
  97.         if(  netBuf.nbflags.spine )splitF(netLog, "SendFastTransfer:FALSE, A Spine\n");
  98.         if(             inReceive )splitF(netLog, "SendFastTransfer:FALSE, We have been called\n");
  99.         };
  100.       splitF(netLog, "Mass Transfer flag ignored\n");
  101.       };
  102.     return FALSE;
  103.  
  104.     }
  105.   if (!CompAvailable(GetCompression(thisNet)))
  106.     {
  107.     if (netDebug)splitF(netLog, "SendFastTransfer:FALSE, No compression set\n");
  108.     return FALSE;
  109.  
  110.     }
  111.   /* do we have rooms to send??? */
  112.   Outgoing = FALSE;
  113.   EachSharedRoom(thisNet, RoomOutgoing, VirtualRoomOutgoing, &Outgoing);
  114.   if (!Outgoing)
  115.     {
  116.     MassTransferSent = TRUE;
  117.     EachSharedRoom(thisNet, UnCacheRoom, UnCacheVirtualRoom, NULL);
  118.     if ( logNetResults && netDebug )splitF(netLog, "SendFastTransfer:FALSE, No rooms to send\n");
  119.     return FALSE;
  120.  
  121.     }
  122.   zero_struct(cmds);
  123.   sPrintf(cmds.fields[0], "%d", GetCompression(thisNet));
  124.   sPrintf(cmds.fields[1], "%d", ZM_PROTOCOL);
  125.   strCpy(cmds.fields[2], "0");
  126.   strCpy(cmds.fields[3], "-1");
  127.   cmds.command = FAST_MSGS;
  128.   protocol = ZM_PROTOCOL;
  129.   if (!Zmodem || FindProtocolCode(Zmodem, FALSE) == -1 ||
  130.   !sendNetCommand(&cmds, "mt"))
  131.     {
  132.     sPrintf(cmds.fields[1], "%d", DEFAULT_PROTOCOL);
  133.     protocol = DEFAULT_PROTOCOL;
  134.     if (!sendNetCommand(&cmds, "mt"))
  135.       {
  136.       if( logNetResults && netDebug )splitF(netLog, "Fast Transfer refused\n");
  137.       return FALSE;
  138.  
  139.       }
  140.  
  141.     }
  142.   if (SendMapFile())
  143.     {
  144.     if (!MapFileAccepted())
  145.       {
  146.       if ( logNetResults && netDebug )splitF(netLog, "SendFastTransfer:FALSE, MAP File problem\n");
  147.       return FALSE;
  148.  
  149.       }
  150.     CacheSystem(thisNet, FALSE);
  151.     outMod(ACK);
  152.     sPrintf(BaseArcName, NETMSGS, CompExtension(GetCompression(thisNet)));
  153.     NetCacheName(ArcFileName, thisNet, BaseArcName);
  154.     if( logNetResults && netDebug )splitF(netLog, "Mass Transfer: %s\n",ArcFileName);
  155.     if (protocol == DEFAULT_PROTOCOL)
  156.       SendHostFile(ArcFileName);
  157.     else
  158.       {
  159.       ExternalTransfer(FindProtocolCode(Zmodem, FALSE), ArcFileName);
  160.       while (MIReady()) inp();
  161.       pause(80);   /* keep the other system from eating our NAK */
  162.  
  163.       }
  164.     if (gotCarrier())
  165.       {
  166.       ITL_Receive(NULL, FALSE, TRUE, putFLChar, fclose);
  167.       if (RecBuf[0] == BAD || !gotCarrier())
  168.         {
  169.         if ( logNetResults && netDebug )splitF(netLog, "SendFastTransfer:FALSE, lost carrier, or bad transmission\n");
  170.         return FALSE;
  171.         };
  172.       MassTransferSent = TRUE;
  173.       EachSharedRoom(thisNet, UnCacheRoom, UnCacheVirtualRoom, NULL);
  174.       MakeNetCacheName(CacheDir, thisNet);
  175.       if (logNetResults && netDebug)splitF(netLog, "CacheDir:%s\n",CacheDir);
  176.       if (ChangeToCacheDir(CacheDir) == 0)
  177.         {
  178.         netBytes = 0l;
  179.         wildCard(getSize, BaseArcName, FALSE, "", FALSE);
  180.         size = netBytes;
  181.         netBytes = 0l;
  182.         wildCard(getSize, CACHED_FILES, FALSE, "", FALSE);
  183.         wildCard(DelFile, ALL_FILES, FALSE, "", FALSE);
  184.         if( logNetResults && netDebug )splitF(netLog, "MT: %ld => %ld\n", netBytes, size);
  185.  
  186.         }
  187.       homeSpace();
  188.       return TRUE;
  189.  
  190.       }
  191.  
  192.     }
  193.   if ( logNetResults && netDebug )splitF(netLog, "SendFastTransfer:FALSE, problem with sendmapfile()\n");
  194.   return FALSE;
  195.  
  196.   }
  197. /*
  198. * RoomOutgoing()
  199. *
  200. * This is responsible for deciding if the given shared room has outgoing
  201. * material in a room eligible for mass transfers.
  202. */
  203. int RoomOutgoing(SharedRoom *room, int system, int index, int roomslot,
  204. char *d)
  205.   {
  206.   if (strLen(roomTab[roomslot].rtname) && HasOutgoing(system, index))
  207.     {
  208.     *d = TRUE;
  209.     return ERROR;
  210.  
  211.     }
  212.   return TRUE;
  213.  
  214.   }
  215. /*
  216. * SendMapFile()
  217. *
  218. * This sends a file containing the names of rooms to share and the filenames
  219. * in the upcoming archive file to map the rooms to.  Format is a series of
  220. * pairs of lines (UNIX style), first the roomname and then the filename.
  221. * blank line signals end of file.
  222. */
  223. char SendMapFile()
  224.   {
  225.   int NormalRoomMap(SharedRoom *room, int system, int index, int roomslot,
  226.   void *d);
  227.   if (!ITL_Send(STARTUP)) return FALSE;
  228.   EachSharedRoom(thisNet, NormalRoomMap, VirtualRoomMap, NULL);
  229.   ITL_Line("");
  230.   return ITL_Send(FINISH);
  231.  
  232.   }
  233. /*
  234. * NormalRoomMap()
  235. *
  236. * This sends the given room's name and cache file name if there is an
  237. * outgoing file pending or one will be built.
  238. */
  239. int NormalRoomMap(SharedRoom *room, int system, int index, int roomslot,
  240. void *d)
  241.   {
  242.   char work[20];
  243.   if (strLen(roomTab[roomslot].rtname) && HasOutgoing(system, index))
  244.     {
  245.     ITL_Line(roomTab[roomslot].rtname);
  246.     sPrintf(work, CACHE_END_NAME, roomslot);
  247.     ITL_Line(work);
  248.  
  249.     }
  250.   return TRUE;
  251.  
  252.   }
  253. /*
  254. * ITL_Line()
  255. *
  256. * Sends the specified line to the SendITLchar function.
  257. */
  258. void ITL_Line(char *data)
  259.   {
  260.   while (*data)
  261.     {
  262.     sendITLchar((int) *data);
  263.     data++;
  264.  
  265.     }
  266.   sendITLchar((int) '\n');
  267.  
  268.   }
  269. /*
  270. * DelFile()
  271. *
  272. * This function kills the named file.
  273. */
  274. void DelFile(DirEntry *f)
  275.   {
  276.   unlink(f->unambig);
  277.  
  278.   }
  279. /*
  280. * MapFileAccepted()
  281. *
  282. * This function is responsible for discovering if the map file is acceptable.
  283. */
  284. char MapFileAccepted()
  285.   {
  286.   FILE *fd;
  287.   char toReturn = TRUE, work[NAMESIZE + 5];
  288.   ToTempArea();
  289.   if (ITL_Receive("moo", FALSE, TRUE, putFLChar, fclose) == ITL_SUCCESS)
  290.     {
  291.     if ((fd = safeopen("moo", READ_ANY)) == NULL)
  292.     toReturn = FALSE;
  293.     else
  294.       {
  295.       GetAString(work, sizeof work, fd);
  296.       if (strLen(work) != 0) toReturn = FALSE;
  297.       fclose(fd);
  298.       unlink("moo");
  299.  
  300.       }
  301.  
  302.     }
  303.   else toReturn = FALSE;
  304.   KillTempArea();
  305.   return toReturn;
  306.  
  307.   }
  308. #define TOP_COMP  4
  309. /*
  310. * netFastTran()
  311. *
  312. * Accept an archive of files?
  313. */
  314. void netFastTran(struct cmd_data *cmds)
  315.   {
  316.   char CheckMap(char *fn, char talk);
  317.   int MTProtocol;
  318.   SYS_FILE fn;
  319.   char work[15];
  320.   MTCompVal  = atoi(cmds->fields[0]);
  321.   MTProtocol = atoi(cmds->fields[1]);
  322.   if (RecMassTransfer || MTCompVal > TOP_COMP || MTCompVal < 0 ||
  323.   !DeCompAvailable(MTCompVal))
  324.     {
  325.     reply(BAD, "nope");
  326.     return;
  327.  
  328.     }
  329.   if (MTProtocol == ZM_PROTOCOL)
  330.     {
  331.     if (!Zmodem || FindProtocolCode(Zmodem, TRUE) == -1)
  332.       {
  333.       reply(BAD, "No protocol");
  334.       return;
  335.  
  336.       }
  337.  
  338.     }
  339.   else if (MTProtocol != DEFAULT_PROTOCOL)
  340.     {
  341.     reply(BAD, "No protocol");
  342.     return;
  343.  
  344.     }
  345.   if (strCmp(cmds->fields[2], "0") != SAMESTRING ||
  346.   strCmp(cmds->fields[3], "-1") != SAMESTRING)
  347.     {
  348.     reply(BAD, " Field 2 & Field 3 no match");
  349.     return;
  350.  
  351.     }
  352.   reply(GOOD, "");
  353.   makeSysName(fn, MAP_FILE, &cfg.netArea);
  354.   if ( logNetResults && netDebug)splitF(netLog, "MAP File:%s\n",fn);
  355.   if (ITL_Receive(fn, FALSE, TRUE, putFLChar, fclose) != ITL_SUCCESS)
  356.     {
  357.     return ;
  358.  
  359.     }
  360.   KillList(&Mappings);
  361.   if (CheckMap(fn, TRUE))
  362.     {
  363.     if( logNetResults )splitF(netLog, "Accepting mass transfer %d\n", MTProtocol);
  364.     if (receive(120) == NAK) return;
  365.  
  366.     sPrintf(work, FAST_RECEIVE, CompExtension(MTCompVal));  /*** bug fix ***/
  367. /*    makeSysName(fn, work, &cfg.netArea); */
  368.     ChangeToCacheDir((char *)&cfg.netArea);           /*** bug fix ***/
  369.  
  370.     if ( logNetResults && netDebug )splitF(netLog, "AMT File(netarea):%s\n",work);
  371.     if (MTProtocol == DEFAULT_PROTOCOL)
  372.       {
  373.       if ( logNetResults && netDebug )splitF(netLog, "Protocol: DEFAULT\n",work);
  374.       if (ITL_Receive(work,FALSE,TRUE, putFLChar, fclose) != ITL_SUCCESS)
  375.         {
  376.         return ;
  377.  
  378.         }
  379.  
  380.       }
  381.     else if (MTProtocol == ZM_PROTOCOL)
  382.       {
  383.       if ( logNetResults && netDebug )splitF(netLog, "Protocol: Zmodem/External\n",work);
  384.       ExternalTransfer(FindProtocolCode(Zmodem, TRUE), work);
  385.       while (MIReady()) inp();
  386.  
  387.       }
  388.     if (access(fn, 0) == 0 )
  389.       {
  390.       reply(GOOD, "");
  391.       /* recovery setup in case of power failure, etc */
  392.       sPrintf(fn, "%s:%d", FAST_RECEIVE, MTCompVal);
  393.       UpdateRecoveryFile(fn);
  394.       RecMassTransfer = TRUE;
  395.       }
  396.     else
  397.       {
  398.       reply(BAD, "No file");
  399.       if( logNetResults )splitF(netLog, "File not received:%s\n",fn);
  400.       makeSysName(fn, MAP_FILE, &cfg.netArea);
  401.       unlink(fn);
  402.  
  403.       }
  404.  
  405.     }
  406.   homeSpace();
  407.   }
  408. /*
  409. * CheckMap()
  410. *
  411. * Checks the map of room names to see if we refuse any.
  412. */
  413. char CheckMap(char *fn, char talk)
  414.   {
  415.   FILE *fd;
  416.   char work[2 * NAMESIZE];
  417.   char toReturn = TRUE, bad;
  418.   FileMap *data;
  419.   RoomSearch arg;
  420.   if (talk && !ITL_Send(STARTUP)) return FALSE;
  421.   if ((fd = safeopen(fn, READ_ANY)) != NULL)
  422.     {
  423.     while (GetAString(work, sizeof work, fd) != NULL)
  424.       {
  425.       bad = TRUE;
  426.       if (strLen(work) == 0) break;
  427.       if (strLen(work) < NAMESIZE)
  428.         {
  429.         strCpy(arg.Room, work);
  430.         if (RoomRoutable(&arg))
  431.           {
  432.           bad = FALSE;
  433.           data = GetDynamic(sizeof *data);
  434.           data->RoomName = strdup(work);
  435.           GetAString(work, sizeof work, fd);
  436.           data->FileName = strdup(work);
  437.           if ( logNetResults && netDebug )splitF(netLog, "MAP Data:RoomName:%s FileName:%s\n"
  438.           ,data->RoomName, data->FileName);
  439.           AddData(&Mappings, data, NULL, FALSE);
  440.  
  441.           }
  442.  
  443.         }
  444.       /* this form lets us respond to several errors with one chunk of code */
  445.       if (bad)
  446.         {
  447.         toReturn = FALSE;
  448.         if (talk) ITL_Line(work);
  449.         GetAString(work, sizeof work, fd);
  450.  
  451.         }
  452.  
  453.       }
  454.     fclose(fd);
  455.  
  456.     }
  457.   else
  458.     {
  459.     printf("Couldn't open %s!\n", fn);
  460.     if (talk) ITL_Line("moo");
  461.     toReturn = FALSE;
  462.  
  463.     }
  464.   if (talk)
  465.     {
  466.     ITL_Line("");
  467.     ITL_Send(FINISH);
  468.  
  469.     }
  470.   return toReturn;
  471.  
  472.   }
  473. /*
  474. * FreeMapping()
  475. *
  476. * Frees a mapping structure.
  477. */
  478. static void FreeMapping(FileMap *data)
  479.   {
  480.   free(data->FileName);
  481.   free(data->RoomName);
  482.   free(data);
  483.  
  484.   }
  485. /*
  486. * KillCacheFiles()
  487. *
  488. * This function kills all cache information concerning a node.  It is called
  489. * when a node is deleted from the nodelist, NOT when caching is simply turned
  490. * off.
  491. */
  492. void KillCacheFiles(int which)
  493.   {
  494.   char ArcFileName[100];
  495.   MakeNetCacheName(ArcFileName, which);
  496.   /* we check this due to the statement after - kill all files! */
  497.   if (ChangeToCacheDir(ArcFileName) == 0)
  498.   wildCard(DelFile, ALL_FILES, FALSE, "", FALSE);
  499.   homeSpace();
  500.   rmdir(ArcFileName);
  501.  
  502.   }
  503. /*
  504. * ReadFastFiles()
  505. *
  506. * This function reads in all of the messages from an Arc file.
  507. */
  508. void ReadFastFiles()
  509.   {
  510.   SYS_FILE fn;
  511.   char work[15];
  512.   void EatMsgFile();
  513.   if (!RecMassTransfer) return;
  514.   RecMassTransfer = FALSE;
  515.   sprintf(work, FAST_RECEIVE, CompExtension(MTCompVal));
  516.   makeSysName(fn, work, &cfg.netArea);
  517.   if ( logNetResults && netDebug)splitF(netLog, "RFF:%s(netarea)\n",fn);
  518.   NetDeCompress(MTCompVal, fn);
  519.   RunList(&Mappings, EatMsgFile);
  520.   KillNetDeCompress();
  521.   if (!cfg.BoolFlags.debug) unlink(fn);
  522.   makeSysName(fn, MAP_FILE, &cfg.netArea);
  523.   if (!cfg.BoolFlags.debug) unlink(fn);
  524.   KillList(&Mappings);
  525.   homeSpace();
  526.   }
  527. /*
  528. * EatMsgFile()
  529. *
  530. * This eats a message file extracted from an archive file.
  531. */
  532. void EatMsgFile(FileMap *data)
  533.   {
  534.   char fn[80];
  535.   char vfn[70];
  536.   int VirtNo;
  537.   RoomSearch arg;
  538.   extern char *SharingRefusal[];
  539.   strCpy(arg.Room, data->RoomName);
  540.   if (!RoomRoutable(&arg))
  541.     {
  542.     if( logNetResults )splitF(netLog, "Ooops - can't find %s\n", data->RoomName);
  543.     return;
  544.  
  545.     }
  546.   if (arg.virtual)
  547.     {
  548.     SetUpForVirtuals(arg.index, &VirtNo, vfn);
  549.     MakeDeCompressedFilename(fn, data->FileName);
  550.     VirtualCopyFileToFile(fn, vfn);
  551.  
  552.     }
  553.   else
  554.     {
  555.     MakeDeCompressedFilename(fn, data->FileName);
  556.     ReadNetRoomFile(arg.index, fn);
  557.  
  558.     }
  559.  
  560.   }
  561. /*
  562. * CacheMessages()
  563. *
  564. * This function is tasked with building cache files as needed.  We loop
  565. * through all the systems in the system list.  Those for which the
  566. * MassTransfer flag is active will cause the system to see if there are
  567. * any messages in the message base that are not in the cache for that
  568. * system.  If any are found, the messages are added to their respective
  569. * files (or create as necessary) and then the compression program is run for
  570. * that particular cache.  Flags must be set appropriately, of course.
  571. */
  572. char CacheUpdated;
  573. void CacheMessages(MULTI_NET_DATA whichNets, char VirtOnly)
  574.   {
  575.   int rover;
  576.   for (rover = 0; rover < cfg.netSize; rover++)
  577.     {
  578.     if ((netTab[rover].ntMemberNets & whichNets))
  579.     CacheSystem(rover, VirtOnly);
  580.  
  581.     }
  582.  
  583.   }
  584. /*
  585. * CacheSystem()
  586. *
  587. * This function caches a single system.  It is separated from CacheMessages()
  588. * so we can cache systems on an individual basis.
  589. */
  590. void CacheSystem(int system, char VirtOnly)
  591.   {
  592.   int CacheRoom(SharedRoom *room, int system, int index, int roomslot, void *d);
  593.   extern void (*NetPrintTarget)(char *format, ...);
  594.   char ArcFileName[60], Files[60], BaseName[40];
  595.   if (!netTab[system].ntflags.MassTransfer) return;
  596.   if (!gotCarrier()) DisableModem(TRUE);
  597.   CacheUpdated = FALSE;
  598.   NetPrintTarget = ToFile;
  599.   EachSharedRoom(system, (VirtOnly) ? NULL : CacheRoom,
  600.   CacheVirtualRoom, NULL);
  601.   if (CacheUpdated)
  602.     {
  603.     putNet(system, &netBuf);
  604.     if (CompAvailable(GetCompression(system)))
  605.       {
  606.       sPrintf(BaseName, NETMSGS, CompExtension(GetCompression(thisNet)));
  607.       NetCacheName(ArcFileName, system, BaseName);
  608.       if ( logNetResults && netDebug )splitF(netLog, "ArcFileName:%s\n",ArcFileName);
  609.       NetCacheName(Files, system, CACHED_FILES);
  610.       if ( logNetResults && netDebug )splitF(netLog, "Files:%s\n",Files);
  611.       Compress(GetCompression(system), Files, ArcFileName);
  612.       if (access(ArcFileName, 0) != 0)
  613.         {
  614.         sPrintf(msgBuf.mbtext, "Compress failed for %s?", netBuf.netName);
  615.         if( logNetResults )splitF(netLog, "ERROR: %s\n", msgBuf.mbtext);
  616.         aideMessage("Net Aide", FALSE);
  617.  
  618.         }
  619.  
  620.       }
  621.     UpdVirtStuff();
  622.  
  623.     }
  624.   if (!gotCarrier()) EnableModem(TRUE);
  625.   NetPrintTarget = mTrPrintf;
  626.  
  627.   }
  628. /*
  629. * CacheRoom()
  630. *
  631. * This caches a room's messages as necessary.
  632. */
  633. int CacheRoom(SharedRoom *room, int system, int index, int roomslot,
  634. void *d)
  635.   {
  636.   extern char PrTransmit;
  637.   char oldNet;
  638.   int MsgCount;
  639.   extern NetInfo NetStyle;
  640.   char work[10], tempNm[3*NAMESIZE], commnd, doit, *name;
  641.   if (roomTab[roomslot].rtlastMessage > room->lastMess &&
  642.   strLen(roomTab[roomslot].rtname))
  643.     {
  644.     if (thisNet != system)
  645.     getNet(system, &netBuf);
  646.     Addressing(system, index, &commnd, &NetStyle.addr1, &NetStyle.addr2,
  647.     &NetStyle.addr3, &name, &doit);
  648.     NetStyle.sendfunc = putFLChar;
  649.     PrTransmit = FALSE;
  650.     sPrintf(work, CACHE_END_NAME, roomslot);
  651.     NetCacheName(tempNm, system, work);
  652.     if ((upfd = safeopen(tempNm, APPEND_ANY)) != NULL)
  653.       {
  654.       oldNet = inNet;
  655.       inNet = NET_CACHE;
  656.       MsgCount = showMessages(NEWoNLY, FALSE,
  657.       room->lastMess, NetRoute);
  658.       inNet = oldNet;
  659.       fclose(upfd);
  660.       SetHighValues(index);
  661.       if (MsgCount == 0 && !GetFA(room->mode))
  662.       unlink(tempNm);
  663.       else if (MsgCount != 0)
  664.         {
  665.         SetFA(netBuf.netRooms[index].mode);
  666.         CacheUpdated = TRUE;
  667.  
  668.         }
  669.  
  670.       }
  671.     PrTransmit = TRUE;
  672.  
  673.     }
  674.   return TRUE;
  675.  
  676.   }
  677. /*
  678. * RecoverMassTransfer()
  679. *
  680. * This function is charged with recovering a mass transfer file that was
  681. * not processed in the last net session due to a crash of some sort.
  682. */
  683. void RecoverMassTransfer(char *line)
  684.   {
  685.   SYS_FILE fn;
  686.   char *colon;
  687.   makeSysName(fn, MAP_FILE, &cfg.netArea);
  688.   RecMassTransfer = TRUE;
  689.   if ( logNetResults && netDebug)splitF(netLog, "Recover from:%s\n",fn);
  690.   CheckMap(fn, FALSE);
  691.   if ((colon = strchr(line, ':')) == NULL) return;
  692.   MTCompVal = atoi(colon + 1);
  693.   ReadFastFiles();
  694.  
  695.   }
  696. /*
  697. * UnCacheRoom()
  698. *
  699. * This turns off the cached flag for a given room shared thing.
  700. */
  701. int UnCacheRoom(SharedRoom *room, int system, int index, int roomslot,
  702. void *d)
  703.   {
  704.   if (strLen(roomTab[roomslot].rtname))
  705.     {
  706.     UnSetFA(netBuf.netRooms[index].mode);
  707.     /* this is valid only so long as we uncache on-line, so in case ... */
  708.     if (inNet != NON_NET) SR_Sent[index] = 1;
  709.  
  710.     }
  711.   return TRUE;
  712.  
  713.   }
  714.